package cn.yj.core.business.service;

import cn.yj.annotation.pagehelper.page.Page;
import cn.yj.api.FileUploadHandler;
import cn.yj.cgs.dba.entity.IntegralGoods;
import cn.yj.cgs.dba.entity.IntegralGoodsType;
import cn.yj.cgs.dba.entity.Message;
import cn.yj.cgs.dba.entity.UserIntegralGoods;
import cn.yj.cgs.dba.entity.vo.ExpressProgress;
import cn.yj.cgs.dba.entity.vo.IntegralGoodsForm;
import cn.yj.cgs.dba.mapper.IntegralGoodsMapper;
import cn.yj.cgs.dba.mapper.IntegralGoodsTypeMapper;
import cn.yj.cgs.dba.mapper.MessageMapper;
import cn.yj.cgs.dba.mapper.UserIntegralGoodsMapper;
import cn.yj.cgs.dba.service.IntegralCommonService;
import cn.yj.common.Enums;
import cn.yj.common.ImageUtils;
import cn.yj.common.NameValue;
import cn.yj.common.UUIdUtils;
import cn.yj.commons.StringPools;
import cn.yj.commons.utils.MapUtils;
import cn.yj.commons.utils.StringUtils;
import cn.yj.entity.Base64Entity;
import cn.yj.params.check.annotation.CheckObjectValue;
import cn.yj.params.check.annotation.KeyValue;
import cn.yj.params.check.annotation.Require;
import cn.yj.tools.exception.ServiceException;
import cn.yj.tools.readconfig.PropertiesUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;

import static cn.yj.commons.utils.FilterNull.isNull;

/**
 * @author 永健
 * @since 2021-06-06 20:10
 */
@Service
public class GoodsService extends ServiceImpl<IntegralGoodsMapper, IntegralGoods> {

    @Resource
    private IntegralGoodsTypeMapper goodsTypeMapper;

    @Resource
    private UserIntegralGoodsMapper userIntegralGoodsMapper;

    @Resource
    private MessageMapper messageMapper;

    @Resource
    private IntegralCommonService integralCommonService;

    public Page<IntegralGoods> pageList(Map<String, Object> params, Page<IntegralGoods> page) {
        baseMapper.findList(params, page);
        return page;
    }

    public List<IntegralGoodsType> getGoodsType() {
        return goodsTypeMapper.selectList(null);
    }

    public Page<IntegralGoodsType> goodsTypePageList(Map<String, Object> params, Page<IntegralGoodsType> page) {
        goodsTypeMapper.pageList(params, page);
        return page;
    }

    @SneakyThrows
    @CheckObjectValue(keyValue = @KeyValue(type = IntegralGoods.class, name = {"goodName", "price", "integralPrice",
            "typeNo", "mainImgUrl", "stock", "content", "status"}))
    public boolean save(IntegralGoodsForm entity) {
        uploadMainImg(entity);
        IntegralGoods integralGoods = new IntegralGoods();
        BeanUtils.copyProperties(entity, integralGoods);
        integralGoods.setGoodsNo(UUIdUtils.getCode());
        integralGoods.setStatus(Enums.IntegralGood.STATUS.valueOf(entity.getStatus()));
        return super.save(integralGoods);
    }

    @CheckObjectValue(keyValue = @KeyValue(type = IntegralGoods.class, name = {"id","goodName", "price", "integralPrice",
            "typeNo", "mainImgUrl", "stock", "content", "status"}))
    public boolean updateById(IntegralGoodsForm entity) throws Exception {
        uploadMainImg(entity);
        IntegralGoods integralGoods = new IntegralGoods();
        BeanUtils.copyProperties(entity, integralGoods);
        integralGoods.setStatus(Enums.IntegralGood.STATUS.valueOf(entity.getStatus()));
        return super.updateById(integralGoods);
    }

    private static File WATER_FILE;
    static {
        WATER_FILE = new File(PropertiesUtils.getStringValue("school-cbd.water-img-path"));
    }
    private void uploadMainImg(IntegralGoodsForm goods) throws Exception {
        String mainImgUrl = goods.getMainImgUrl();

        if (!mainImgUrl.startsWith("http")) {

            try {
                // 水印处理
                mainImgUrl = ImageUtils.addImageWaterMark(mainImgUrl, WATER_FILE);
            } catch (IOException e) {
                log.error("水印处理异常",e);
            }

            String upload = FileUploadHandler.getInstant().upload(new Base64Entity(mainImgUrl,
                    Enums.Minio.Bucket.goods.name().concat("/").concat(UUIdUtils.getCode()).concat(StringPools.JPG)));
            goods.setMainImgUrl(upload);
        }
    }

    @CheckObjectValue(keyValue = @KeyValue(type = IntegralGoodsType.class, name = {"name"}))
    public boolean saveAndUpdateType(IntegralGoodsType type) {
        if (StringUtils.isNull(type.getId())) {
            type.setTypeNo(UUIdUtils.getCode());
            return goodsTypeMapper.insert(type) > Enums.Common.ZERO;
        }
        type.setTypeNo(null);
        return goodsTypeMapper.updateById(type) > Enums.Common.ZERO;
    }

    public boolean deletedTypeByNo(@Require String[] typeNos) {
        int row = 0;
        for (int i = 0; i < typeNos.length; i++) {
            if (baseMapper.selectCount(new QueryWrapper<IntegralGoods>().lambda().eq(IntegralGoods::getTypeNo,
                    typeNos[i])) > Enums.Common.ZERO) {
                throw new ServiceException("当前商品类型和商品有绑定");
            }
            int j = goodsTypeMapper.delete(new UpdateWrapper<IntegralGoodsType>().lambda().eq(IntegralGoodsType::getTypeNo, typeNos[i]));
            row = row + j;
        }
        if (row == typeNos.length) {
            return true;
        }
        throw new ServiceException((typeNos.length - row) + " 条删除失败");
    }

    public boolean deletedGoodsById(@Require Integer[] goodsId) {
        return baseMapper.deleteBatchIds(Arrays.asList(goodsId)) > Enums.Common.ZERO;
    }

    @CheckObjectValue(keyValue = @KeyValue(type = Map.class, name = {"id", "status"}))
    public boolean changeStatus(Map<String, String> body) {
        IntegralGoods integralGoods = new IntegralGoods();
        integralGoods.setId(Integer.parseInt(body.get("id")));
        String status = body.get("status");
        integralGoods.setStatus(Enums.IntegralGood.STATUS.valueOf(status));
        return baseMapper.updateById(integralGoods) > Enums.Common.ZERO;
    }

    @CheckObjectValue(keyValue = @KeyValue(type = Map.class, name = {"id", "stock"}))
    public boolean addStock(Map<String, Object> params) {
        IntegralGoods goods = super.getById(Integer.parseInt(params.get("id").toString()));
        isNull(goods, "找不到商品");
        goods.setStock(goods.getStock() + Integer.parseInt(params.get("stock").toString()));
        return super.updateById(goods);
    }


    public Page<UserIntegralGoods> goodsChangeRecordsPageList(
            Map<String, Object> params, @Require Page<UserIntegralGoods> page) {
        userIntegralGoodsMapper.findList(params, page);
        return page;
    }


    public ExpressProgress getProgress(@Require String expressNo) {
        UserIntegralGoods userIntegralGoods =
                userIntegralGoodsMapper.selectOne(new QueryWrapper<UserIntegralGoods>().lambda().eq(UserIntegralGoods::getUserGoodsNo, expressNo));
        if (StringUtils.isNull(userIntegralGoods)) {
            throw new ServiceException(String.format("找不到该记录:%s", expressNo));
        }
        List<Map<String, Object>> maps =
                new ArrayList<>(Enums.IntegralGood.PROGRESS.get(userIntegralGoods.getExpressStatus().name()));
        maps.forEach(map -> {
            map.put("isCurrentStatus", false);
            if (userIntegralGoods.getExpressStatus().name().equals(map.get("status").toString())) {
                map.put("isCurrentStatus", true);
            }
        });
        ExpressProgress expressProgress = new ExpressProgress();
        expressProgress.setExpressNo(userIntegralGoods.getExpressNo());
        expressProgress.setCreateTime(userIntegralGoods.getSendTime());
        expressProgress.setProgress(maps);
        expressProgress.setCurrentStatus(userIntegralGoods.getExpressStatus().getMsg());
        return expressProgress;
    }

    @Transactional
    @CheckObjectValue(keyValue = @KeyValue(type = Map.class, name = {"userGoodsNo", "expressNo", "expressCompany",
            "expressStatus"}))
    public boolean sendGoods(Map<String, Object> params) {
        UserIntegralGoods integralGoods = userIntegralGoodsMapper.selectByNoForUpdate(MapUtils.getStringVal(params,
                "userGoodsNo"));
        UserIntegralGoods userIntegralGoods = new UserIntegralGoods();
        userIntegralGoods.setExpressNo(MapUtils.getStringVal(params, "expressNo"));
        userIntegralGoods.setExpressCompany(MapUtils.getStringVal(params, "expressCompany"));
        if (StringUtils.isNull(integralGoods.getSendTime())) {
            userIntegralGoods.setSendTime(new Date());
        }
        Enums.IntegralGood.EXPRESS_STATUS expressStatus =
                Enums.IntegralGood.EXPRESS_STATUS.valueOf(MapUtils.getStringVal(params, "expressStatus"));
        userIntegralGoods.setExpressStatus(expressStatus);
        if (expressStatus==Enums.IntegralGood.EXPRESS_STATUS.DOING){
            messageMapper.insert(new Message("同学你好，您的积分兑换商品，已经发出，请您自己关注物流信息哦~ <br/> 可到 积分-兑换记录里查看  <br/> 物流单号为："+userIntegralGoods.getExpressNo(),"商品发出",integralGoods.getUserCode()));
        }else if (expressStatus==Enums.IntegralGood.EXPRESS_STATUS.CANCEL){
            messageMapper.insert(new Message("同学你好，您的积分兑换商品已被取消，积分已回退账号~ <br/> 可到 积分-兑换记录里查看 ","商品发出",integralGoods.getUserCode()));
            // 积分还原
            integralCommonService.updateIntegral(integralGoods.getUserCode(),integralGoods.getAmount(),true,Enums.IntegralWater.SOURCE.CANCEL_EXCHANGE,null,null);
        }else if (expressStatus==Enums.IntegralGood.EXPRESS_STATUS.SEND_TO){
            messageMapper.insert(new Message("同学你好，您的积分兑换商品，已送达，请您自己关注物流信息哦~ <br/> 可到 积分-兑换记录里查看  <br/> 物流单号为："+userIntegralGoods.getExpressNo(),"商品发出",integralGoods.getUserCode()));
        }

        return userIntegralGoodsMapper.update(userIntegralGoods,
                new UpdateWrapper<UserIntegralGoods>().lambda().eq(UserIntegralGoods::getUserGoodsNo,
                        MapUtils.getStringVal(params, "userGoodsNo"))) > Enums.Common.ZERO;
    }

    public List<NameValue> getExpressStatus() {
        return Enums.IntegralGood.expressStatusToList();
    }
}
